package com.prodog.gamemodule.fight.session;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil;
import com.prodog.gamemodule.fight.action.entity.FightAction;
import com.prodog.gamemodule.fight.action.handler.AttackHandler;
import com.prodog.gamemodule.fight.ai.FightAI;
import com.prodog.gamemodule.fight.effect.entity.FightEffect;
import com.prodog.gamemodule.fight.effect.manager.EffectHandlerManager;
import com.prodog.gamemodule.fight.fightobj.entity.FightObj;
import com.prodog.gamemodule.fight.round.handler.RoundEventHandler;
import com.prodog.gamemodule.fight.util.FightUtil;
import com.prodog.gamemodule.fight.wrapper.FightSessionWrapper;
import com.prodog.utils.bean.SpringBeanUtils;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
@NoArgsConstructor
@Document("g_fight_session")
public class FightSession {
    private String id;
    private Map<Object, FightObj> objsByUuid;   //所有单位
    private Map<String, FightObj> redObjs;  //红方单位
    private Map<String, FightObj> blueObjs; //蓝方单位
    private FightSessionObjInfo objInfo;
    private int victory = -1;
    private int round;  //当前回合

    public static final Map<Integer, String> coolTimePrefixMap = new HashMap<>();

    static {
        coolTimePrefixMap.put(FightAction.ACTION_TYPE_ATTACK, "SKILL:");
        coolTimePrefixMap.put(FightAction.ACTION_TYPE_USE_ITEM, "ITEM:");
    }

    public FightSession(List<FightObj> fightObjs) {
        this.objsByUuid = CollUtil.toMap(fightObjs, new LinkedHashMap<>(), obj -> obj.getUuid());
        List<FightObj> redList = fightObjs.stream().filter(obj -> obj.getFlag() == 0).collect(Collectors.toList());
        List<FightObj> blueList = fightObjs.stream().filter(obj -> obj.getFlag() == 1).collect(Collectors.toList());
        this.redObjs = CollUtil.toMap(redList, new LinkedHashMap<>(), obj -> obj.getUuid());
        this.blueObjs = CollUtil.toMap(blueList, new LinkedHashMap<>(), obj -> obj.getUuid());
        nextRound();
        //触发入场时被动
        for (FightObj obj : objsByUuid.values()) {
            for (FightEffect effect : obj.getEffects()) {
                EffectHandlerManager.onFightStart(this, effect, obj);
            }
        }
    }

    //检查所有单位是否已准备好
    public boolean checkReadyOver() {
        for (FightObj obj : objsByUuid.values()) {
            if (obj.getAction() == null && obj.getFightAi() != null) {
                FightAI fightAI = null;
                try {
                    fightAI = (FightAI) ReflectUtil.newInstance(Class.forName(obj.getFightAi()));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                    try {
                        fightAI = (FightAI) ReflectUtil.newInstance(Class.forName("com.prodog.gamemodule.fight.ai.impl.NormalFightAI"));
                    } catch (ClassNotFoundException ex) {
                        ex.printStackTrace();
                    }
                }
                fightAI.autoFight(this, obj);
            }
        }
        return !objsByUuid.values().stream().anyMatch(obj -> obj.getAction() == null && obj.getState() != 2);
    }

    public void fight(StringBuilder msg) {
        if (!checkReadyOver()) return;
        msg.append("                    【第" + round + "回合】\n");
        List<FightObj> objs;
        //按照敏捷度排序后按顺序进行行为处理
        do {
            objs = FightUtil.orderBySpped(objsByUuid);
            if (objs.size() > 0) {
                FightObj obj = objs.get(0);
                for (FightEffect effect : obj.getEffects()) {
                    EffectHandlerManager.beforeAction(this, effect, obj);
                }
                if (obj.getAction().getType() == 1) {
                    new AttackHandler(this, obj).action();
                }
            }
        } while (objs.size() > 0);
        msg.append(objInfo.getInfo());

        //回合事件处理器
        new RoundEventHandler(this).handle();
        //检查并处理获胜
        boolean over = checkOver();
        if (over) return;
        //下一个回合
        nextRound();
        //如果所有单位设置好行为 直接运算下一回合作战
        if (checkReadyOver()) fight(msg);
    }

    private boolean checkOver() {
        victory = FightUtil.getVictory(this);
        if (victory != -1) {
            return true;
        }
        return false;
    }

    private void nextRound() {
        //清除本回合动作
        objsByUuid.values().forEach(obj -> obj.setAction(null));
        objsByUuid.values().forEach(obj -> obj.setOver(false));
        objInfo = new FightSessionObjInfo();
        round++;
    }

    public String run(String uuid) {
        StringBuilder sb = new StringBuilder("战斗信息:\n");
        this.fight(sb);
        sb.append("\n");
        if (uuid != null) {
            sb.append(FightUtil.fightInfo(this, uuid));
        } else {
            sb.append(FightUtil.fightInfo(this));
        }
        FightSessionWrapper wrapper = SpringBeanUtils.getBean(FightSessionWrapper.class);
        wrapper.save(this);
        return sb.toString();
    }
}
